/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package edu.pdx.cs.guavadata.domain;

import edu.pdx.cs.guavadata.AppData;
import edu.pdx.cs.guavadata.DBConnection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
 *
 * @author VuTran
 */
public class String extends Domain {
    private java.lang.Integer width;
    
    public String(int w) {
        this.width = w;
    }
    
    public String() {
        this.width = -1;
    }
    
    @Override
    public boolean validate(Object o) {
        if (!(o instanceof java.lang.String)) return false;
        if ((width >= 0) && ((java.lang.String) o).length() > width) return false;
        return true;
    }

    @Override
    public Object convertString(java.lang.String s) throws DomainConversionException {
        if ((width >= 0) && (s.length() > width))
            throw new DomainConversionException("\"" + s + "\" is longer than width" + width + ".");
        return s;
    }

    @Override
    public Class getNaiveType() {
        return java.lang.String.class;
    }

    @Override
    public java.lang.String getDBType() {
        if ((width < 0) || (width > 8000)) return "text";
        return "varchar(" + width + ")";
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof String)) return false;
        if (((String) obj).width != this.width && ((String) obj).width != -1 
                && this.width != -1)
            return false;
        return true;
    }

    @Override
    public int hashCode() {
        return String.class.hashCode() + width.hashCode();
    }

    @Override
    public java.lang.String toString() {
        return "String";
    }

    
    @Override
    public Domain upcast() {
        return null;
    }

    @Override
    public Object upcastValue(Object o) throws Exception {
        return null;
    }

    @Override
    public Domain merge(Domain d) {
        if (!(d instanceof String)) return null;
        String sd = (String) d;
        
        // If either length is null, return a new string domain of long length
        if ((this.width < 0) || (sd.width < 0)) return new String();

        // Otherwise, return a string domain with the larger width
        if (this.width > sd.width) return new String((int)this.width);
        return new String((int)sd.width);
    }

    @Override
    public boolean isOrdered() {
        return true;
    }

    @Override
    public boolean canContain() {
        return true;
    }

    @Override
    public Domain clone() {
        return new String(this.width);
    }

    @Override
    public Element ToXml(Document xdoc) {
        Element xe = xdoc.createElement("Domain");
        xe.setAttribute("Type", "String");
        if (width >= 0) xe.setAttribute("Width", width.toString());
        return xe;
    }
    
    public static String fromElement(Element e) {
        if (e.hasAttribute("Width")) {
            return new String(java.lang.Integer.parseInt(e.getAttribute("Width")));
        } 
        return new String();
    }

    public static String FromDBInfoRow(ResultSet dr) {
        int length = -1;
        
        try {
            // get the first row
            dr.next();
            
            if (dr.getObject("CHARACTER_MAXIMUM_LENGTH") != null) {
                length = java.lang.Integer.parseInt(dr.getObject("CHARACTER_MAXIMUM_LENGTH").toString());
            }
            
            if (AppData.testForEnum && length <= 50 && length != -1) {
                ResultSet rs = DBConnection.executeQuery("select " + dr.getString("Column_Name") + ", count(*) as count from " + dr.getString("Table_Name") + " group by " + dr.getString("Column_Name"));
                
                if (rs.next()) {
                    java.lang.String message = "Testing string column, "+  dr.getString("Column_Name") + ", in "+ dr.getString("Table_Name") + " for possible enumeration.\n \nStatistics: \n";

                    java.lang.String indCount = dr.getString("Column_Name") + "\tCount\n---------------------------------\n";
                    
                    rs.beforeFirst();
                    while (rs.next()) {
                        indCount = indCount + (rs.getString(dr.getString("Column_Name")) == null ? "NULL" : rs.getString(dr.getString("Column_Name")));
                    }
                    
                    message = message + indCount;
                    
                    int res = JOptionPane.showConfirmDialog(null, message, "Enumeration Test", JOptionPane.YES_NO_CANCEL_OPTION);
                }
            }
      } catch (SQLException ex) {
            Logger.getLogger(String.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        if (length != -1)
            return new String(length);
        else
            return new String();
    }
}
